package treeedit;

import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.util.Hashtable;
import java.util.Map.Entry;

public class BZAddressParser {
	/**
	 * This function parses Trees from file located on @filePath. The file
	 * should be in format of Bolzano address data set.
	 */
	public static Hashtable<Integer, Tree> parse(String filePath) {
		Hashtable<Integer, Tree> hash = new Hashtable<Integer, Tree>();
		try {
			BufferedReader br = new BufferedReader(new FileReader(filePath));
			String line;
			while ((line = br.readLine()) != null) {
				line = line.trim();
				if (line.startsWith("#")) {
					continue;
				}
				int i = line.indexOf(":");
				int id = Integer.parseInt(line.substring(0, i));
				char[] data = line.toCharArray();
				Tree tempTree = parseTree(data, i + 1, data.length - 1);
				tempTree.init();
				hash.put(id, tempTree);
			}
		} catch (IOException e) {
			e.printStackTrace();
			hash = null;
		}
		// System.out.println("Parsing finished. Trees added: " + hash.size());
		return hash;
	}

	public static Tree parseTree(String filePath) {
		try {
			BufferedReader br = new BufferedReader(new FileReader(filePath));
			String line;
			while ((line = br.readLine()) != null) {
				return parseTree(line.toCharArray(), line.indexOf(":") + 1,
						line.length() - 1);
			}
		} catch (IOException ex) {
			ex.printStackTrace();
		}
		return null;
	}

	private static Tree parseTree(char[] line, int from, int to) {
		Tree t = null;
		if (line[from] == '{' && line[to] == '}' && from < to) {
			t = new Tree();
			int li = ++from;
			while (line[from] != '{' && from < to)
				from++;
			if (li < from)
				t.setName(new String(line, li, from - li));
			while (from < to) {
				li = from;
				int d = 0;
				while (++from < to) {
					if (line[from] == '}' && d == 0)
						break;
					if (line[from] == '{')
						d--;
					if (line[from] == '}')
						d++;
				}
				if (d == 0)
					t.addChild(parseTree(line, li, from));
				while (line[from] != '{' && from < to)
					from++;
			}
		}
		return t;
	}

	public static String getTreeString(Tree tree) {
		StringBuilder sb = new StringBuilder();
		sb.append('{');
		sb.append(tree.getName());
		if (!tree.isLeaf()) {
			for (Tree child : tree.getChildren()) {
				sb.append(getTreeString(child));
			}
		}
		sb.append('}');
		return sb.toString();
	}

	public static String getForestString(Hashtable<Integer, Tree> forest) {
		StringBuilder sb = new StringBuilder();
		for (Entry<Integer, Tree> pair : forest.entrySet()) {
			sb.insert(0, String.format("%s:%s\n", pair.getKey(),
					getTreeString(pair.getValue())));
		}
		return sb.toString();
	}
}
